package bancosys.tec.persist.entities.domain;

import java.util.ArrayList;
import java.util.Collection;

import javax.persistence.Column;
import javax.persistence.DiscriminatorColumn;
import javax.persistence.DiscriminatorType;
import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.Table;

import jmine.tec.persist.annotation.Alias;
import jmine.tec.persist.annotation.Comment;
import jmine.tec.persist.annotation.Comments;
import jmine.tec.persist.annotation.Constraint;
import jmine.tec.persist.annotation.Constraints;
import jmine.tec.persist.annotation.DiscriminatorComment;

import org.hibernate.annotations.Cascade;
import org.hibernate.annotations.CascadeType;
import org.hibernate.annotations.Filter;
import org.hibernate.annotations.Filters;

import bancosys.tec.component.Documentation;
import bancosys.tec.persist.authorization.annotation.DisplayName;
import bancosys.tec.persist.base.enumx.ApacheIntValuedEnumMock;
import bancosys.tec.persist.base.enumx.ApacheStringValuedEnumMock;
import bancosys.tec.persist.base.enumx.JavaEnumMock;
import bancosys.tec.persist.bussobj.AuthPersistableBusinessObject;

/**
 * @created 11.07.2007
 * @author Gustavo Almeida
 */
@Entity
@Table(name = "PAI")
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@Filters({ @Filter(name = "authFilter", condition = "auth = :auth") })
@DisplayName("Pai (BO p/ UnitTest)")
@DiscriminatorColumn(name = "DESCRIMINADOR", discriminatorType = DiscriminatorType.INTEGER)
@DiscriminatorValue("42")
@DiscriminatorComment("PAI")
@Alias("P")
@Documentation("Entidade pai.")
public class Pai extends AuthPersistableBusinessObject {
    private Long id;

    private Pai filhoComCascade;

    private Pai filhoSemCascade;

    private Collection<Pai> colecaoComCascade = new ArrayList<Pai>();

    private Collection<Pai> colecaoSemCascade = new ArrayList<Pai>();

    private String name;

    private JavaEnumMock javaEnumMock;

    private JavaEnumMock outroJavaEnumMock;

    private ApacheIntValuedEnumMock apacheIntEnumMock;

    private ApacheStringValuedEnumMock apacheStringEnumMock;

    @Id
    @Column(name = "ID")
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Documentation("Coluna de identificador.")
    public Long getId() {
        return this.id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    @ManyToMany(fetch = FetchType.LAZY)
    @Cascade({ CascadeType.ALL, CascadeType.DELETE_ORPHAN })
    @JoinTable(name = "PAI_PAI_COM_CASCADE", inverseJoinColumns = { @JoinColumn(name = "PAI_INVERSE_JOIN", nullable = false, updatable = false) }, joinColumns = { @JoinColumn(name = "PAI_JOIN", nullable = false, updatable = false) })
    @Alias("PPCCAS")
    @DisplayName("Coleção com cascade")
    @Comments({ @Comment(table = "PAI_PAI_COM_CASCADE", value = "Join table do relacionamento de pai com pai com cascade."),
            @Comment(table = "PAI_PAI_COM_CASCADE", column = "PAI_JOIN", value = "Coluna de pai join."),
            @Comment(table = "PAI_PAI_COM_CASCADE", column = "PAI_INVERSE_JOIN", value = "Coluna de join inverso.") })
    public Collection<Pai> getColecaoComCascade() {
        return this.colecaoComCascade;
    }

    public void setColecaoComCascade(Collection<Pai> colecaoComCascade) {
        this.colecaoComCascade = colecaoComCascade;
    }

    @ManyToMany(fetch = FetchType.LAZY)
    @JoinTable(name = "PAI_PAI_SEM_CASCADE", inverseJoinColumns = { @JoinColumn(name = "PAI_INVERSE_JOIN", nullable = false, updatable = false) }, joinColumns = { @JoinColumn(name = "PAI_JOIN", nullable = false, updatable = false) })
    @Alias("PPSCAS")
    @Comments({ @Comment(table = "PAI_PAI_SEM_CASCADE", value = "Join table do relacionamento de pai com pai com cascade."),
            @Comment(table = "PAI_PAI_SEM_CASCADE", column = "PAI_INVERSE_JOIN", value = "Coluna de join inverso."),
            @Comment(table = "PAI_PAI_SEM_CASCADE", column = "PAI_JOIN", value = "Coluna de pai join.") })
    @DisplayName("Coleção sem cascade")
    public Collection<Pai> getColecaoSemCascade() {
        return this.colecaoSemCascade;
    }

    public void setColecaoSemCascade(Collection<Pai> colecaoSemCascade) {
        this.colecaoSemCascade = colecaoSemCascade;
    }

    @ManyToOne(fetch = FetchType.LAZY)
    @Cascade({ CascadeType.ALL })
    @JoinColumn(name = "FILHO_COM_CASCADE")
    @DisplayName("Filho com cascade")
    @Documentation("Coluna de join com pai.")
    public Pai getFilhoComCascade() {
        return this.filhoComCascade;
    }

    public void setFilhoComCascade(Pai filhoComCascade) {
        this.filhoComCascade = filhoComCascade;
    }

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "FILHO_SEM_CASCADE")
    @DisplayName("Filho sem cascade")
    public Pai getFilhoSemCascade() {
        return this.filhoSemCascade;
    }

    public void setFilhoSemCascade(Pai filhoSemCascade) {
        this.filhoSemCascade = filhoSemCascade;
    }

    /**
     * @return
     */
    @Column(name = "NOME")
    @DisplayName("Nome")
    @Documentation("Coluna com o nome da entidade pai.")
    public String getName() {
        return this.name;
    }

    /**
     * Define o name.
     * 
     * @param name O name a ser definido.
     */
    public void setName(String name) {
        this.name = name;
    }

    /**
     * @return the javaEnumMock
     */
    @Column(name = "JAVA_ENUM")
    @Documentation("Comment da coluna de java enum.")
    @Constraints({ @Constraint(condition = "JAVA_ENUM < 1 AND JAVA_ENUM > -1", suffix = "2") })
    public JavaEnumMock getJavaEnumMock() {
        return this.javaEnumMock;
    }

    /**
     * @param javaEnumMock the javaEnumMock to set
     */
    public void setJavaEnumMock(JavaEnumMock javaEnumMock) {
        this.javaEnumMock = javaEnumMock;
    }

    /**
     * @return the apacheIntEnumMock
     */
    @Column(name = "APACHE_INT_ENUM")
    public ApacheIntValuedEnumMock getApacheIntEnumMock() {
        return this.apacheIntEnumMock;
    }

    /**
     * @param apacheIntEnumMock the apacheIntEnumMock to set
     */
    public void setApacheIntEnumMock(ApacheIntValuedEnumMock apacheIntEnumMock) {
        this.apacheIntEnumMock = apacheIntEnumMock;
    }

    /**
     * @return the apacheStringEnumMock
     */
    @Column(name = "APACHE_STRING_ENUM")
    public ApacheStringValuedEnumMock getApacheStringEnumMock() {
        return this.apacheStringEnumMock;
    }

    /**
     * @param apacheStringEnumMock the apacheStringEnumMock to set
     */
    public void setApacheStringEnumMock(ApacheStringValuedEnumMock apacheStringEnumMock) {
        this.apacheStringEnumMock = apacheStringEnumMock;
    }

    /**
     * @return the outroJavaEnumMock
     */
    @Column(name = "OUTRO_JAVA_ENUM")
    public JavaEnumMock getOutroJavaEnumMock() {
        return this.outroJavaEnumMock;
    }

    /**
     * @param outroJavaEnumMock the outroJavaEnumMock to set
     */
    public void setOutroJavaEnumMock(JavaEnumMock outroJavaEnumMock) {
        this.outroJavaEnumMock = outroJavaEnumMock;
    }

    @Override
    public String toString() {
        return "Pai(" + this.id + "," + this.name + ")";
    }
}